home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-29  |  16.3 KB  |  755 lines

  1. /*
  2.  *  Window Maker window manager
  3.  * 
  4.  *  Copyright (c) 1997, 1998 Alfredo K. Kojima
  5.  * 
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  19.  *  USA.
  20.  */
  21.  
  22. #include "wconfig.h"
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #include <string.h>
  28. #include <sys/stat.h>
  29. #include <sys/types.h>
  30. #include <fcntl.h>
  31.  
  32. #include <X11/Xlib.h>
  33. #include <X11/Xutil.h>
  34.  
  35.  
  36. /* Xlocale.h and locale.h are the same if X_LOCALE is undefind in wconfig.h,
  37.  * and if X_LOCALE is defined, X's locale emulating functions will be used.
  38.  * See Xlocale.h for more information.
  39.  */
  40. #include <X11/Xlocale.h>
  41.  
  42. #define MAINFILE
  43.  
  44. #include "WindowMaker.h"
  45. #include "window.h"
  46. #include "funcs.h"
  47. #include "menu.h"
  48. #include "keybind.h"
  49. #include "xmodifier.h"
  50. #include "defaults.h"
  51. #include "session.h"
  52. #include "dialog.h"
  53.  
  54. #include <proplist.h>
  55.  
  56. /****** Global Variables ******/
  57.  
  58. /* general info */
  59.  
  60. Display    *dpy;
  61.  
  62. char *ProgName;
  63.  
  64. unsigned int ValidModMask = 0xff;
  65.  
  66. /* locale to use. NULL==POSIX or C */
  67. char *Locale=NULL;
  68.  
  69. int wScreenCount=0;
  70.  
  71. WPreferences wPreferences;
  72.  
  73.  
  74. proplist_t wDomainName;
  75. proplist_t wAttributeDomainName;
  76.  
  77. WShortKey wKeyBindings[WKBD_LAST];
  78.  
  79. /* defaults domains */
  80. WDDomain *WDWindowMaker = NULL;
  81. WDDomain *WDRootMenu = NULL;
  82. WDDomain *WDWindowAttributes = NULL;
  83.  
  84.  
  85. /* XContexts */
  86. XContext wWinContext;
  87. XContext wAppWinContext;
  88. XContext wStackContext;
  89.  
  90. /* Atoms */
  91. Atom _XA_WM_STATE;
  92. Atom _XA_WM_CHANGE_STATE;
  93. Atom _XA_WM_PROTOCOLS;
  94. Atom _XA_WM_TAKE_FOCUS;
  95. Atom _XA_WM_DELETE_WINDOW;
  96. Atom _XA_WM_SAVE_YOURSELF;
  97. Atom _XA_WM_CLIENT_LEADER;
  98. Atom _XA_WM_COLORMAP_WINDOWS;
  99. Atom _XA_WM_COLORMAP_NOTIFY;
  100.  
  101. Atom _XA_GNUSTEP_WM_ATTR;
  102. Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
  103. Atom _XA_GNUSTEP_WM_RESIZEBAR;
  104. Atom _XA_GNUSTEP_TITLEBAR_STATE;
  105.  
  106. Atom _XA_WINDOWMAKER_MENU;
  107. Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
  108. Atom _XA_WINDOWMAKER_STATE;
  109.  
  110. Atom _XA_WINDOWMAKER_WM_FUNCTION;
  111. Atom _XA_WINDOWMAKER_NOTICEBOARD;
  112. Atom _XA_WINDOWMAKER_COMMAND;
  113.  
  114. Atom _XA_WINDOWMAKER_ICON_SIZE;
  115. Atom _XA_WINDOWMAKER_ICON_TILE;
  116.  
  117.  
  118. #ifdef OFFIX_DND
  119. Atom _XA_DND_PROTOCOL;
  120. Atom _XA_DND_SELECTION;
  121. #endif
  122.  
  123. /* cursors */
  124. Cursor wCursor[WCUR_LAST];
  125.  
  126. /* last event timestamp for XSetInputFocus */
  127. Time LastTimestamp;
  128. /* timestamp on the last time we did XSetInputFocus() */
  129. Time LastFocusChange;
  130.  
  131. #ifdef SHAPE
  132. Bool wShapeSupported;
  133. int wShapeEventBase;
  134. #endif
  135.  
  136. #ifdef KEEP_XKB_LOCK_STATUS
  137. Bool wXkbSupported;
  138. int wXkbEventBase;
  139. #endif
  140.  
  141. /* special flags */
  142. char WProgramState = WSTATE_NORMAL;
  143. char WDelayedActionSet = 0;
  144.  
  145. /* temporary stuff */
  146. int wVisualID = -1;
  147.  
  148.  
  149. /******** End Global Variables *****/
  150.  
  151. static char *DisplayName = NULL;
  152.  
  153. static char **Arguments;
  154.  
  155. static int ArgCount;
  156.  
  157. extern void EventLoop();
  158. extern void StartUp();
  159.  
  160. static Bool multiHead = True;
  161.  
  162. /* stdi/o for log shell */
  163. static int LogStdIn = -1, LogStdOut = -1, LogStdErr = -1;
  164.  
  165.  
  166. void
  167. Exit(int status)
  168. {
  169. #ifdef XSMP_ENABLED
  170.     wSessionDisconnectManager();
  171. #endif
  172.     if (dpy)
  173.     XCloseDisplay(dpy);
  174.  
  175.     exit(status);
  176. }
  177.  
  178.  
  179. void
  180. Restart(char *manager, Bool abortOnFailure)
  181. {
  182.     char *prog=NULL;
  183.     char *argv[MAX_RESTART_ARGS];
  184.     int i;
  185.  
  186.     if (manager && manager[0]!=0) {
  187.     prog = argv[0] = strtok(manager, " ");
  188.     for (i=1; i<MAX_RESTART_ARGS; i++) {
  189.         argv[i]=strtok(NULL, " ");
  190.         if (argv[i]==NULL) {
  191.         break;
  192.         }
  193.     }
  194.     }
  195.     if (dpy) {
  196. #ifdef XSMP_ENABLED
  197.     wSessionDisconnectManager();
  198. #endif
  199.     XCloseDisplay(dpy);
  200.     dpy = NULL;
  201.     }
  202.     if (!prog) {
  203.         execvp(Arguments[0], Arguments);
  204.         wfatal(_("failed to restart Window Maker."));
  205.     } else {
  206.         execvp(prog, argv);
  207.         wsyserror(_("could not exec %s"), prog);
  208.     }
  209.     if (abortOnFailure)
  210.         exit(-1);
  211. }
  212.  
  213.  
  214.  
  215. void
  216. SetupEnvironment(WScreen *scr)
  217. {
  218.     char *tmp, *ptr;
  219.     char buf[16];
  220.  
  221.     if (multiHead) {
  222.         tmp = wmalloc(strlen(DisplayName)+64);
  223.         sprintf(tmp, "DISPLAY=%s", XDisplayName(DisplayName));
  224.         ptr = strchr(strchr(tmp, ':'), '.');
  225.         if (ptr)
  226.         *ptr = 0;
  227.         sprintf(buf, ".%i", scr->screen);
  228.         strcat(tmp, buf);
  229.         putenv(tmp);
  230.     }
  231.     tmp = wmalloc(60);
  232.     sprintf(tmp, "WRASTER_COLOR_RESOLUTION%i=%i", scr->screen, 
  233.         scr->rcontext->attribs->colors_per_channel);
  234.     putenv(tmp);
  235. }
  236.  
  237.  
  238.  
  239.  
  240. typedef struct {
  241.     WScreen *scr;
  242.     char *command;
  243. } _tuple;
  244.  
  245.  
  246. static void
  247. shellCommandHandler(pid_t pid, unsigned char status, _tuple *data)
  248. {
  249.     if (status == 127) {
  250.     char *buffer;
  251.  
  252.     buffer = wstrappend(_("Could not execute command: "), data->command);
  253.  
  254.     wMessageDialog(data->scr, _("Error"), buffer, _("OK"), NULL, NULL);
  255.     free(buffer);
  256.     } else if (status != 127) {
  257.     /*
  258.     printf("%s: %i\n", data->command, status);
  259.      */
  260.     }
  261.  
  262.     free(data->command);
  263.     free(data);
  264. }
  265.  
  266.  
  267. void
  268. ExecuteShellCommand(WScreen *scr, char *command)
  269. {
  270.     static char *shell = NULL;
  271.     pid_t pid;
  272.  
  273.     /*
  274.      * This have a problem: if the shell is tcsh (not sure about others)
  275.      * and ~/.tcshrc have /bin/stty erase ^H somewhere on it, the shell
  276.      * will block and the command will not be executed.
  277.     if (!shell) {
  278.     shell = getenv("SHELL");
  279.     if (!shell)
  280.         shell = "/bin/sh";
  281.     }
  282.      */
  283.     shell = "/bin/sh";
  284.  
  285.     pid = fork();
  286.     
  287.     if (pid==0) {
  288.  
  289.     SetupEnvironment(scr);
  290.  
  291. #ifdef HAVE_SETPGID
  292.     setpgid(0, 0);
  293. #endif
  294.     execl(shell, shell, "-c", command, NULL);
  295.     wsyserror("could not execute %s -c %s", shell, command);
  296.     Exit(-1);
  297.     } else if (pid < 0) {
  298.     wsyserror("cannot fork a new process");
  299.     } else {
  300.     _tuple *data = wmalloc(sizeof(_tuple));
  301.     
  302.     data->scr = scr;
  303.     data->command = wstrdup(command);
  304.  
  305.     wAddDeathHandler(pid, (WDeathHandler*)shellCommandHandler, data);
  306.     }
  307. }
  308.  
  309.  
  310. /*
  311.  *---------------------------------------------------------------------------
  312.  * StartLogShell
  313.  *     Start a shell that will receive all stdin and stdout from processes
  314.  * forked by wmaker.
  315.  *---------------------------------------------------------------------------
  316.  */
  317. void
  318. StartLogShell(WScreen *scr)
  319. {
  320.     int in_fd[2];
  321.     int out_fd[2];
  322.     int err_fd[2];
  323.     pid_t pid;
  324.     
  325.     SetupEnvironment(scr);
  326.     
  327.     if (pipe(in_fd) < 0) {
  328.     wsyserror("could not create pipe for log shell\n");
  329.     return;
  330.     }
  331.     if (pipe(out_fd) < 0) {
  332.     wsyserror("could not create pipe for log shell\n");
  333.     close(in_fd[0]);
  334.     close(in_fd[1]);
  335.     return;
  336.     }
  337.     if (pipe(err_fd) < 0) {
  338.     wsyserror("could not create pipe for log shell\n");
  339.     close(out_fd[0]);
  340.     close(out_fd[1]);
  341.     close(in_fd[0]);
  342.     close(in_fd[1]);
  343.     return;
  344.     }
  345.  
  346.     pid = fork();
  347.     if (pid < 0) {
  348.     wsyserror("could not fork a new process for log shell\n");
  349.     return;
  350.     } else if (pid == 0) {    
  351.     close(in_fd[0]);
  352.     close(out_fd[1]);
  353.     close(err_fd[1]);
  354.     
  355.     close(0);
  356.     close(1);
  357.     close(2);
  358.  
  359.     if (dup2(in_fd[1], 0) < 0) {
  360.         wsyserror("could not redirect stdin for log shell\n");
  361.         exit(1);
  362.     }
  363.     if (dup2(out_fd[1], 1) < 0) {
  364.         wsyserror("could not redirect stdout for log shell\n");
  365.         exit(1);
  366.     }
  367.     if (dup2(err_fd[1], 2) < 0) {
  368.         wsyserror("could not redirect stderr for log shell\n");
  369.         exit(1);
  370.     }
  371.  
  372.     close(in_fd[1]);
  373.     close(out_fd[1]);
  374.     close(err_fd[1]);
  375.  
  376.     execl("/bin/sh", "/bin/sh", "-c", wPreferences.logger_shell, NULL);
  377.     wsyserror("could not execute %s\n", wPreferences.logger_shell);
  378.     exit(1);
  379.     } else {
  380.     close(in_fd[1]);
  381.     close(out_fd[0]);
  382.     close(err_fd[0]);
  383.     
  384.     LogStdIn = in_fd[1];
  385.     LogStdOut = out_fd[0];
  386.     LogStdErr = err_fd[0];
  387.     }
  388. }
  389.  
  390.  
  391. /*
  392.  *---------------------------------------------------------------------
  393.  * wAbort--
  394.  *     Do a major cleanup and exit the program
  395.  * 
  396.  *---------------------------------------------------------------------- 
  397.  */
  398. void
  399. wAbort(Bool dumpCore)
  400. {
  401.     int i;
  402.     WScreen *scr;
  403.  
  404.     for (i=0; i<wScreenCount; i++) {
  405.     scr = wScreenWithNumber(i);
  406.     if (scr)
  407.         RestoreDesktop(scr);
  408.     }
  409.     printf(_("%s aborted.\n"), ProgName);
  410.     if (dumpCore)
  411.     abort();
  412.     else
  413.     exit(1);
  414. }
  415.  
  416.  
  417. void
  418. print_help()
  419. {
  420.     printf(_("Usage: %s [options]\n"), ProgName);
  421.     puts(_("The Window Maker window manager for the X window system"));
  422.     puts("");
  423.     puts(_(" -display host:dpy    display to use"));
  424. #ifdef USECPP
  425.     puts(_(" --no-cpp         disable preprocessing of configuration files"));
  426. #endif
  427.     puts(_(" --no-dock        do not open the application Dock"));
  428.     puts(_(" --no-clip        do not open the workspace Clip"));
  429.     puts(_(" --no-autolaunch    do not autolaunch applications"));
  430.     puts(_(" --dont-restore    do not restore saved session"));
  431.  
  432.     puts(_(" --locale locale        locale to use"));
  433.  
  434.     puts(_(" --visual-id visualid    visual id of visual to use"));
  435.     puts(_(" --static        do not update or save configurations"));
  436. #ifdef DEBUG
  437.     puts(_(" --synchronous        turn on synchronous display mode"));
  438. #endif
  439.     puts(_(" --version        print version and exit"));
  440.     puts(_(" --help            show this message"));
  441. }
  442.  
  443.  
  444.  
  445. void
  446. check_defaults()
  447. {
  448.     char *path;
  449.  
  450.     path = wdefaultspathfordomain("");
  451.     if (access(path, R_OK)!=0) {
  452.     wfatal(_("could not find user GNUstep directory (%s).\n"
  453.          "Make sure you have installed Window Maker correctly and run wmaker.inst"),
  454.            path);
  455.     exit(1);
  456.     }
  457.     
  458.     free(path);
  459. }
  460.  
  461.  
  462. static void
  463. execInitScript()
  464. {
  465.     char *file;
  466.     char *paths = wstrappend(wusergnusteppath(), ":"DEF_CONFIG_PATHS);
  467.  
  468.     file = wfindfile(paths, DEF_INIT_SCRIPT);
  469.     free(paths);
  470.  
  471.     if (file) {
  472.     if (system(file) != 0) {
  473.         wsyserror(_("%s:could not execute initialization script"), file);
  474.     }
  475. #if 0
  476.     if (fork()==0) {
  477.         execl("/bin/sh", "/bin/sh", "-c", file, NULL);
  478.         wsyserror(_("%s:could not execute initialization script"), file);
  479.         exit(1);
  480.     }
  481. #endif
  482.     free(file);
  483.     }
  484. }
  485.  
  486.  
  487. void
  488. ExecExitScript()
  489. {
  490.     char *file;
  491.     char *paths = wstrappend(wusergnusteppath(), ":"DEF_CONFIG_PATHS);
  492.  
  493.     file = wfindfile(paths, DEF_EXIT_SCRIPT);
  494.     free(paths);
  495.  
  496.     if (file) {
  497.     if (system(file) != 0) {
  498.         wsyserror(_("%s:could not execute exit script"), file);
  499.     }
  500. #if 0
  501.     if (fork()==0) {
  502.         execl("/bin/sh", "/bin/sh", "-c", file, NULL);
  503.         wsyserror(_("%s:could not execute exit script"), file);
  504.         exit(1);
  505.     }
  506. #endif
  507.     free(file);
  508.     }
  509. }
  510.  
  511. #if 0
  512. char*
  513. getFullPath(char *path)
  514. {
  515.     char buffer[1024];
  516.     char *tmp;
  517.     char *basep = (char*)buffer;
  518.  
  519.     if (*path != '/' && getcwd(buffer, 1023)) {
  520.  
  521.     for (;;) {
  522.         if (strncmp(path, "../", 3)==0) {
  523.         path += 3;
  524.         basep = strchr(basep, '/');
  525.         if (!basep || *path==0)
  526.             break;
  527.         }
  528.     }
  529.     if (*path == '/' || strncmp(path, "./",2)==0) {
  530.         tmp = 
  531.     }
  532.  
  533.     /*
  534.      * path
  535.      * ./path
  536.      * ../path
  537.      * ../../path
  538.      */
  539.     
  540.  
  541.     } else {
  542.     return wstrappend(path);
  543.     }
  544.  
  545.     return tmp;
  546. }
  547. #endif
  548.  
  549. int
  550. main(int argc, char **argv)
  551. {
  552.     int i, restart=0;
  553.     char *str;
  554.     int d, s;
  555. #ifdef DEBUG
  556.     Bool doSync = False;
  557. #endif
  558.     setlocale(LC_ALL, "");
  559.  
  560.     wsetabort(wAbort);
  561.  
  562.     /* for telling WPrefs what's the name of the wmaker binary being ran */
  563.  
  564.     str = wstrappend("WMAKER_BIN_NAME=", argv[0]);
  565.     putenv(str);
  566.  
  567.     ArgCount = argc;
  568.     Arguments = argv;
  569.  
  570.     WMInitializeApplication("WindowMaker", &argc, argv);
  571.  
  572.  
  573.     ProgName = strrchr(argv[0],'/');
  574.     if (!ProgName)
  575.       ProgName = argv[0];
  576.     else
  577.       ProgName++;
  578.  
  579.  
  580.     restart = 0;
  581.     
  582.     memset(&wPreferences, 0, sizeof(WPreferences));
  583.     
  584.     if (argc>1) {
  585.     for (i=1; i<argc; i++) {
  586. #ifdef USECPP
  587.         if (strcmp(argv[i], "-nocpp")==0
  588.         || strcmp(argv[i], "--no-cpp")==0) {
  589.         wPreferences.flags.nocpp=1;
  590.         } else
  591. #endif
  592.         if (strcmp(argv[i], "-no-autolaunch")==0
  593.         || strcmp(argv[i], "--no-autolaunch")==0) {
  594.         wPreferences.flags.noautolaunch = 1;
  595.         } else if (strcmp(argv[i], "-dont-restore")==0
  596.         || strcmp(argv[i], "--dont-restore")==0) {
  597.         wPreferences.flags.norestore = 1;
  598.         } else if (strcmp(argv[i], "-nodock")==0
  599.         || strcmp(argv[i], "--no-dock")==0) {
  600.         wPreferences.flags.nodock=1;
  601.         } else if (strcmp(argv[i], "-noclip")==0
  602.                || strcmp(argv[i], "--no-clip")==0) {
  603.         wPreferences.flags.noclip=1;
  604.         } else if (strcmp(argv[i], "-version")==0
  605.                || strcmp(argv[i], "--version")==0) {
  606.         printf("Window Maker %s\n", VERSION);
  607.         exit(0);
  608.         } else if (strcmp(argv[i], "--global_defaults_path")==0) {
  609.         printf("%s/WindowMaker\n", SYSCONFDIR);
  610.         exit(0);
  611. #ifdef DEBUG
  612.             } else if (strcmp(argv[i], "--synchronous")==0) {
  613.                 doSync = 1;
  614. #endif
  615.         } else if (strcmp(argv[i], "-locale")==0
  616.                || strcmp(argv[i], "--locale")==0) {
  617.         i++;
  618.         if (i>=argc) {
  619.             wwarning(_("too few arguments for %s"), argv[i-1]);
  620.             exit(0);
  621.         }
  622.         Locale = argv[i];
  623.         } else if (strcmp(argv[i], "-display")==0) {
  624.         i++;
  625.         if (i>=argc) {
  626.             wwarning(_("too few arguments for %s"), argv[i-1]);
  627.             exit(0);
  628.         }
  629.         DisplayName = argv[i];
  630.         } else if (strcmp(argv[i], "-visualid")==0
  631.                || strcmp(argv[i], "--visual-id")==0) {
  632.         i++;
  633.         if (i>=argc) {
  634.             wwarning(_("too few arguments for %s"), argv[i-1]);
  635.             exit(0);
  636.         }
  637.         if (sscanf(argv[i], "%i", &wVisualID)!=1) {
  638.             wwarning(_("bad value for visualid: \"%s\""), argv[i]);
  639.             exit(0);
  640.         }
  641.         } else if (strcmp(argv[i], "-static")==0
  642.                || strcmp(argv[i], "--static")==0) {
  643.  
  644.         wPreferences.flags.noupdates = 1;
  645. #ifdef XSMP_ENABLED
  646.         } else if (strcmp(argv[i], "-clientid")==0
  647.                || strcmp(argv[i], "-restore")==0) {
  648.         i++;
  649.         if (i>=argc) {
  650.             wwarning(_("too few arguments for %s"), argv[i-1]);
  651.             exit(0);
  652.         }
  653. #endif
  654.         } else if (strcmp(argv[i], "--help")==0) {
  655.         print_help();
  656.         exit(0);
  657.         } else {
  658.         printf(_("%s: invalid argument '%s'\n"), argv[0], argv[i]);
  659.         printf(_("Try '%s --help' for more information\n"), argv[0]);
  660.         exit(1);
  661.         }
  662.     }
  663.     }
  664.     
  665.     if (!wPreferences.flags.noupdates) {
  666.     /* check existence of Defaults DB directory */
  667.     check_defaults();
  668.     }
  669.  
  670.  
  671.     if (!Locale) {
  672.     Locale = getenv("LC_ALL");
  673.     }
  674.     if (!Locale) {
  675.         Locale = getenv("LANG");
  676.     }
  677.  
  678.     setlocale(LC_ALL, "");
  679.  
  680.     if (!Locale || strcmp(Locale, "C")==0 || strcmp(Locale, "POSIX")==0) 
  681.       Locale = NULL;
  682. #ifdef I18N
  683.     if (getenv("NLSPATH"))
  684.       bindtextdomain("WindowMaker", getenv("NLSPATH"));
  685.     else
  686.       bindtextdomain("WindowMaker", LOCALEDIR);
  687.     textdomain("WindowMaker");
  688.  
  689.     if (!XSupportsLocale()) {
  690.     wwarning(_("X server does not support locale"));
  691.     }
  692.  
  693.     if (XSetLocaleModifiers("") == NULL) {
  694.      wwarning(_("cannot set locale modifiers"));
  695.     }
  696. #endif
  697.  
  698.     if (Locale) {
  699.     char *ptr;
  700.  
  701.     Locale = wstrdup(Locale);
  702.     ptr = strchr(Locale, '.');
  703.     if (ptr)
  704.         *ptr = 0;
  705.     }
  706.  
  707.     /* open display */
  708.     dpy = XOpenDisplay(DisplayName);
  709.     if (dpy == NULL) {
  710.     wfatal(_("could not open display \"%s\""), XDisplayName(DisplayName));
  711.     exit(1);
  712.     }
  713.  
  714.     if (fcntl(ConnectionNumber(dpy), F_SETFD, FD_CLOEXEC) < 0) {
  715.     wsyserror("error setting close-on-exec flag for X connection");
  716.     exit(1);
  717.     }
  718.  
  719.     /* check if the user specified a complete display name (with screen).
  720.      * If so, only manage the specified screen */
  721.     if (DisplayName)
  722.     str = strchr(DisplayName, ':');
  723.     else
  724.     str = NULL;
  725.  
  726.     if (str && sscanf(str, "%i.%i", &d, &s)==2)
  727.     multiHead = False;
  728.  
  729.     DisplayName = XDisplayName(DisplayName);
  730.     str = wmalloc(strlen(DisplayName)+64);
  731.     sprintf(str, "DISPLAY=%s", DisplayName);
  732.     putenv(str);
  733.  
  734. #ifdef DEBUG
  735.     if (doSync)
  736.         XSynchronize(dpy, True);
  737. #endif
  738.  
  739.     wXModifierInitialize();
  740.  
  741. #ifdef XSMP_ENABLED
  742.     wSessionConnectManager(argv, argc);
  743. #endif
  744.     
  745.     StartUp(!multiHead);
  746.     
  747.     if (wScreenCount==1)
  748.     multiHead = False;
  749.  
  750.     execInitScript();
  751.  
  752.     EventLoop();
  753.     return -1;
  754. }
  755.